package com.daxia.bumall.service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import com.daxia.bumall.basemodel.CoreUser;
import com.daxia.bumall.common.AuditStatus;
import com.daxia.bumall.common.UserType;
import com.daxia.bumall.dao.ICoreUserDAO;
import com.daxia.bumall.dto.CompanyDTO;
import com.daxia.bumall.dto.DesignerDTO;
import com.daxia.bumall.dto.UserDTO;
import com.daxia.bumall.model.Authority;
import com.daxia.bumall.model.Role;
import com.daxia.bumall.model.User;
import com.daxia.bumall.security.NotAuthException;



@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService, Serializable {
	private static Logger logger = Logger.getLogger(MyUserDetailsService.class);
    private static final long serialVersionUID = 1L;

    @Autowired
    private ICoreUserDAO userDAO;
    @Autowired
    private UserService userService;
	@Autowired
	private UserRoleService userRoleService;
	@Autowired
	private UserAuthorityService userAuthorityService;
	@Autowired
	private RoleAuthorityService roleAuthorityService;
	@Autowired
	private DesignerService designerService;
	@Autowired
	private CompanyService companyService;
    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
	        return doLoad(username);
    }

	private UserDetails doLoad(String username) {
		if (logger.isDebugEnabled()) {
			logger.debug("开始登陆, " + username);
		}
	    CoreUser user = userDAO.loadUserByUsername(username);
        if (user == null) {
        	if (logger.isDebugEnabled()) {
				logger.debug("用户不存在, " + username);
			}
            throw new UsernameNotFoundException("Can't find user by username [" + username + "]");
        }
        
        UserDTO userDTO = userService.load(user.getId());
        if (userDTO.getType() == null || userDTO.getType() == UserType.Normal.getValue()) {
        	if (logger.isDebugEnabled()) {
				logger.debug("正常用户不允许登陆" + username);
			}
        	throw new UsernameNotFoundException("NormalUser");
        }
        if (userDTO.getType() != null) {
        	if(userDTO.getType() == UserType.Designer.getValue()) {    //设计师需要审核
        		DesignerDTO designer = new DesignerDTO();
        		designer.setUser(new User());
        		designer.getUser().setId(user.getId());
        		designer = designerService.findOne(designer);
        		if(designer == null) {
        			if (logger.isDebugEnabled()) {
						logger.debug("没有找到designer对象, " + username);
					}
        			notAuth();
        		} else {
        			if(designer.getAuditStatus() == null || designer.getAuditStatus() != AuditStatus.Success.getValue()) {
        				if (logger.isDebugEnabled()) {
							logger.debug("设计师未审核, " + username);
						}
        				notAuth();
        			}
        		}
        	} else if(userDTO.getType() == UserType.Factory.getValue()) {   //工厂用户不能登录,2016-11-15改为可以登录
        		//throw new UsernameNotFoundException("对不起，工厂用户不能进行登录操作，请注册其他类型用户...");
        	} else if(userDTO.getType() == UserType.DecorateCompany.getValue()) {    //装修公司需要审核
        		CompanyDTO company = new CompanyDTO();
        		company.setUser(userDTO);
        		//company.setQueryUserId(userDTO.getId());
        		company = companyService.findOne(company);
        		if(company == null) {
        			if (logger.isDebugEnabled()) {
						logger.debug("未找到company对象, " + username);
					}
        			notAuth();
        		} else {
        			if(company.getAuditStatus() == null || company.getAuditStatus() != AuditStatus.Success.getValue()) {
        				if (logger.isDebugEnabled()) {
							logger.debug("装修公司未审核, " + username);
						}
        				notAuth();
        			}
        		}
        	}
        }
        
        // 最终用户拥有的所有权限
        List<GrantedAuthority> finalAuthorities = new ArrayList<GrantedAuthority>();
        
        // 找角色，然后找出每个角色拥有的权限
        List<Role> roles = userRoleService.findRolesByUserId(user.getId());
        for (Role role : roles) {
            List<Authority> authorities = roleAuthorityService.findByAuthoritiesByRoleId(role.getId());
            addToFinalAuthorities(finalAuthorities, authorities);
        }
        
        // 找权限
        List<Authority> authorities = userAuthorityService.findAuthoritiesByUserId(user.getId());
        addToFinalAuthorities(finalAuthorities, authorities);
        
        if (user instanceof User) {
        	if (((User) user).getType() != UserType.Normal.getValue()) {
        		finalAuthorities.add(new GrantedAuthority() {
					
					@Override
					public String getAuthority() {
						return "manager";
					}
				});
        	}
        }
        user.setAuthorities(finalAuthorities);
        
        return user;
    }

	private void notAuth() {
		throw new NotAuthException("NotAuth");
		
	}

    private void addToFinalAuthorities(List<GrantedAuthority> finalAuthorities, List<Authority> authorities) {
        for (Authority authority : authorities) {
            addToFinalAuthorities(finalAuthorities, authority);
        }
    }
    
    private void addToFinalAuthorities(List<GrantedAuthority> finalAuthorities, Authority authority) {
        final String code = authority.getCode();
        if (StringUtils.isNotBlank(code)) {
            finalAuthorities.add(new GrantedAuthority() {
                private static final long serialVersionUID = 1L;
                @Override
                public String getAuthority() {
                    return code;
                }
            });
        }
        
        if (CollectionUtils.isNotEmpty(authority.getChildrens())) {
            for (Authority child : authority.getChildrens()) {
                addToFinalAuthorities(finalAuthorities, child);
            }
        }
    }

}
